/**
 * 
 */
package com.unlp.javaclickers.docente.logic.impl;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;

import com.google.common.collect.Maps;
import com.google.common.collect.Queues;
import com.unlp.javaclickers.docente.logic.ServicioProblema;
import com.unlp.javaclickers.modelo.Condicion;
import com.unlp.javaclickers.modelo.Problema;

/**
 * @author Pablo
 * 
 */
public class ServicioProblemaImpl implements ServicioProblema {

	@Override
	public Problema getFirstProblem(Set<Problema> problemas) {
		Iterator<Problema> it = problemas.iterator();
		while (it.hasNext()) {
			Problema p = it.next();
			if (p.isPrimero()) {
				return p;
			}
		}
		return null;
	}

	@Override
	public Problema getNextProblem(Problema problema, int cantCorrectas,
			int totalAlumnos) {
		int porcentaje = (cantCorrectas * 100) / totalAlumnos;
		for (Condicion c : problema.getCondiciones()) {
			if (porcentaje >= c.getValorMin() && porcentaje <= c.getValorMax()) {
				return c.getProblemaSiguiente();
			}
		}
		return null;
	}

	@Override
	public boolean isCyclic(Set<Problema> problemas) {
		ConcurrentLinkedQueue<Problema> q = Queues.newConcurrentLinkedQueue();
		long counter = 0;

		Map<Problema, Integer> contadorVertices = Maps.newConcurrentMap();
		Iterator<Problema> it = problemas.iterator();
		while (it.hasNext()) {
			Problema p = it.next();
			contadorVertices.put(p, 0);
		}
		Iterator<Problema> iteratorMap = contadorVertices.keySet().iterator();
		while (iteratorMap.hasNext()) {
			Problema p = iteratorMap.next();
			for (Condicion condicion : p.getCondiciones()) {
				if (condicion.getProblemaSiguiente() != null) {
					contadorVertices.put(condicion.getProblemaSiguiente(),
							contadorVertices.get(condicion
									.getProblemaSiguiente()) + 1);
				}
			}
		}

		for (Map.Entry<Problema, Integer> entry : contadorVertices.entrySet()) {
			if (entry.getValue() == 0) {
				q.add(entry.getKey());
			}
		}

		if (q.isEmpty()) {
			return true;
		}

		for (counter = 0; !q.isEmpty(); counter++) {
			Problema problema = q.poll();
			for (Condicion c : problema.getCondiciones()) {
				Problema problemaDest = c.getProblemaSiguiente();
				if (problemaDest != null) {
					contadorVertices.put(problemaDest,
							contadorVertices.get(problemaDest) - 1);
					if (contadorVertices.get(problemaDest) == 0) {
						q.offer(problemaDest);
					}
				}
			}
		}
		if (counter != problemas.size()) {
			return true;
		}
		return false;

	}

}
